﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Asteroids.Entities.Components;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework;

namespace Asteroids.Entities.EntityProcessors
{
    public class PlayerEntityProcessor : EntityProcessor
    {
        private KeyboardState _old, _new;
        private float _currentDelta;
        private MouseState _oldMouseState, _newMouseState;
        private Vector2 _mouseLocation;
        private EntityManager _entityManager;
        private ProjectileEntityTemplate _projTemplate;

        public PlayerEntityProcessor(EntityManager entityMan)
        {
            _entityManager = entityMan;
            _projTemplate = new ProjectileEntityTemplate();
        }

        public override void Update(float delta)
        {
            _old = _new;
            _new = Keyboard.GetState();

            _oldMouseState = _newMouseState;
            _newMouseState = Mouse.GetState();

            _mouseLocation = new Vector2(_newMouseState.X, _newMouseState.Y);

            _currentDelta = delta;

            base.Update(delta);
        }
        public override void Process(Entity e)
        {
            PlayerControllerComponent playerController = e.QueryComponent<PlayerControllerComponent>();
            TransformComponent transformComponent = e.QueryComponent<TransformComponent>();
            PhysicsComponent physicsComponent = e.QueryComponent<PhysicsComponent>();

            if (physicsComponent != null && transformComponent != null && playerController != null)
            {
                Vector2 movementDelta = Vector2.Zero;

                float speedDelta = _currentDelta;
                if (KeyHeld(Keys.W))
                    movementDelta.X -= speedDelta;
                else if (KeyHeld(Keys.S))
                    movementDelta.X += speedDelta;

                if (KeyHeld(Keys.A))
                    movementDelta.Y += speedDelta;
                else if (KeyHeld(Keys.D))
                    movementDelta.Y -= speedDelta;

                if (KeyHeld(Keys.LeftShift))
                    physicsComponent.Velocity = physicsComponent.Velocity - ((0.75f * _currentDelta) * physicsComponent.Velocity);
                Vector2 differenceVector;
                Vector2 playerLocation = transformComponent.Location;

                Vector2.Subtract(ref playerLocation, ref _mouseLocation, out differenceVector);


                if (KeyHeld(Keys.Space))
                    FireProjectile(_mouseLocation - playerLocation, playerLocation);

                float rotation = (float)Math.Atan2(differenceVector.Y, differenceVector.X);

                Matrix rotationMatrix;
                Matrix.CreateRotationZ(rotation, out rotationMatrix);

                Vector2.Transform(ref movementDelta, ref rotationMatrix, out movementDelta);
                float speed = 50f;

                Vector2.Multiply(ref movementDelta, speed, out movementDelta);

                physicsComponent.Acceleration = movementDelta;
                transformComponent.Rotation = rotation + MathHelper.PiOver2;
            }
        }

        private void FireProjectile(Vector2 direction, Vector2 location)
        {
            var bullet = _entityManager.CreateEntity(null, _projTemplate);

            direction.Normalize();

            bullet.QueryComponent<TransformComponent>().Location = location;
            bullet.QueryComponent<PhysicsComponent>().Velocity = direction * 5;
        }

        public bool KeyPressed(Keys key)
        { return _old.IsKeyDown(key) && _new.IsKeyUp(key); }

        public bool KeyHeld(Keys key)
        { return _new.IsKeyDown(key); }
    }
}
